#ifndef SCON_PROFILE_H_
#define SCON_PROFILE_H_

#include <string>
#include <windows.h>

#ifdef __SCON_TEST__
#include "gtest/gtest_prod.h"
#endif

#ifdef __SCON_DEBUG__
#include <iostream>
#include <iomanip>
#endif

namespace SCon {

struct File {
/*
класс File является обстракцией понятия "файл" в ОС, определяет все необходимые характеристики
объекта,
а также способы создания и уничтожения объекта.
Конструкторы класса File закрыты от публичного доступа, чтобы обязать пользователя 
пользоваться функциями Create() и Close()
*/
#ifdef __SCON_TEST__
	friend class ProfileTest;
	FRIEND_TEST(ProfileTest, FileCreateTest);
	FRIEND_TEST(ProfileTest, FileCloseTest);
	FRIEND_TEST(ProfileTest, FileCalculateSharedModeTest);
	FRIEND_TEST(ProfileTest, FileCalculateOpenModeTest);
	FRIEND_TEST(ProfileTest, FileCalculateAccessModeTest);
#endif

	enum CreationFlag{//флаги определяющие режим создания физического файла
		CREATE = 0x1,//создавать, если файл не существует
		OPEN = 0x2,//открывать, если файл существует
		RECREATE = 0x4,//всегда пересоздавать файл
		READ = 0x8,//доступ на чтение
		WRITE = 0x10,//доступ на запись
		SHARED_READ = 0x20,//задать возможность доступа по чтению к файлу из других процессов
		SHARED_WRITE = 0x40,//задавать возможность доступа по записи к файлу из других процессов
	};

	HANDLE fileDescriptor_;
	std::string path_;
	int creationMode_;

/*
Функция
	static File* Create(const std::string& path, int creationMode, std::string* errorMessage);
предназначена для создания объектов File.
Принимаемые параметры:
- path - физический путь к реальному файлу (файл может существовать или нет)
- creationMode - режим создания файл, предпочтительно задавать константами CreationFlag,
возможно задание нескольких флагов путем объединения их побитовым ИЛИ (флаги RECREATE
CREATE и OPEN являются взаимоисключающими).
Диапазон значений 9..120
Следует учитывать, что если задан флаг File::CREATE, и файл существует, то функция не сработает и вернет 0.
- errorMessage - сюда можно писать ошибки, может быть равен 0
Возвращаемые параметры:
Указатель на вновь созданный объект файл или 0, если создать не получилось
*/
	static File* Create(const std::string& path, int creationMode = CREATE | READ, std::string* errorMessage = 0);

/*
Функция
	static bool Close(File* cp, std::string* errorMessage);
Закрывает созданное соединение и освобождает ресурсы выделенные под объект File.
Принимаемые параметры:
- cp - указатель, на объект File, ресурсы которого надо освободить
- errorMessage - сюда можно писать ошибки, может быть равен 0
Возвращаемое значение:
true - если все хорошо, false - если плохо.
*/
	static bool Close(File* cp, std::string* errorMessage = 0);

/*
Функция
	static bool CheckParameter(int operationMode, std::string* errorMessage); 
	Проверяет параметр на допустимость значения
Принимаемые параметры:
	creationMode - параметр, который необходимо проверить
	errorMessage - сюда можно писать ошибки, может быть равен 0.
Возвращаемое значение:
true - параметр имеет допустимое значение, false - в противном случае.
*/
	static bool CheckParameter(int creationMode, std::string* errorMessage); 

#ifndef __SCON_TEST__
protected:
	~File(){}
#endif

private:
	File():fileDescriptor_(0), path_("") {}

	File(const std::string& path, int creationMode)
		:fileDescriptor_(0),
		path_(path),
		creationMode_(creationMode)
	{}

/*
Функция
	int CalculateSharedMode(int creationMode)
является служебной. Преобразует параметр creationMode в параметр dwShareMode функции
WINAPI CreateFile()
*/
	int CalculateSharedMode(int creationMode);

/*
Функция
	int CalculateOpenMode(int creationMode);
является служебной. Преобразует параметр creationMode в параметр dwCreationDisposition
функции WINAPI CreateFile()
Учтите что если заданы одновременно два и более флага RECREATE, CREATE, OPEN, то учитывается
только младший по значению
*/
	int CalculateOpenMode(int creationMode);

/*
Функция
	int CalculateAccessMode(int creation mode);
является служебной. Преобразует параметр creationMode в параметр dwDesiredAccess функции WINAPI
CreateFile()
*/
	int CalculateAccessMode(int creationMode);

//запрещаем копирование объекта
	File(const File&);
	File& operator=(const File&);
};//end of declaration File

} /* SCon */ 

#endif /* end of include guard: SCON_PROFILE_H_ */

